using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace DP.Sharepoint.Workflow
{



    /// <summary>

    /// Class used to decode an InfoPath attachment.

    /// Pulls the file name and the decoded file from either a base 64 byte array or string.

    /// </summary>

    public class InfoPathAttachmentDecoder
    {
        
       

        //  Private string to hold the attachment name.

        string _fileName;



        //  Private byte array to hold the decoded attachment.

        byte[] _decodedFile;



        /// <summary>

        /// The name of the file within the InfoPath attachment.

        /// </summary>

        public string Filename
        {

            get { return _fileName; }

        }



        /// <summary>

        /// The decoded file within the InfoPath attachment.

        /// </summary>

        public byte[] DecodedFile
        {

            get { return _decodedFile; }

        }



        /// <summary>

        /// Constructor for the InfoPathAttachmentDecoder Class

        /// </summary>

        /// <param name="base64EncodedString">The attachment represented by a string</param>

        public InfoPathAttachmentDecoder(string base64EncodedString)
        {

            //  Use unicode encoding.

            Encoding _encoding = Encoding.Unicode;



            //  The byte array containing the data.

            byte[] _data = Convert.FromBase64String(base64EncodedString);



            //  Use a memory stream to access the data.

            using (MemoryStream _memoryStream = new MemoryStream(_data))
            {

                //  Create a binary reader from the stream.

                BinaryReader _theReader = new BinaryReader(_memoryStream);



                //  Create a byte array to hold the header data.

                byte[] _headerData = _theReader.ReadBytes(16);



                //  Find the file size before finding the file name.

                int _fileSize = (int)_theReader.ReadUInt32();



                //  Get the file name.

                int _attachmentNameLength = (int)_theReader.ReadUInt32() * 2;

                byte[] _fileNameBytes = _theReader.ReadBytes(_attachmentNameLength);

                _fileName = _encoding.GetString(_fileNameBytes, 0, _attachmentNameLength - 2);



                //  Get the decoded attachment.            

                _decodedFile = _theReader.ReadBytes(_fileSize);

            }

        }

        

        /// <summary>

        /// Constructor for the InfoPathAttachmentDecoder Class

        /// </summary>

        /// <param name="base64EncodedBytes">The attachment represented by a byte array</param>

        public InfoPathAttachmentDecoder(byte[] base64EncodedBytes) : this(Convert.ToBase64String(base64EncodedBytes)) { }



        /// <summary>

        /// Static method that gets the file from the attachment.

        /// </summary>

        /// <param name="base64EncodedString">The attachment represented by a string</param>

        /// <returns>Returns a byte array of the file in the attachment.</returns>

        public static byte[] DecodeInfoPathAttachment(string base64EncodedString)
        {

            //  Create an instance of the InfoPathAttachmentDecoder

            InfoPathAttachmentDecoder _infoPathAttachmentDecoder = new InfoPathAttachmentDecoder(base64EncodedString);



            //  Return the decoded file.

            return _infoPathAttachmentDecoder.DecodedFile;

        }



        /// <summary>

        /// Static method that gets the file from the attachment.

        /// </summary>

        /// <param name="base64EncodedBytes">The attachment represented by a byte array</param>

        /// <returns>Returns a byte array of the file in the attachment.</returns>

        public static byte[] DecodeInfoPathAttachment(byte[] base64EncodedBytes)
        {

            //  Create an instance of the InfoPathAttachmentDecoder

            InfoPathAttachmentDecoder _infoPathAttachmentDecoder = new InfoPathAttachmentDecoder(base64EncodedBytes);

            //  Return the decoded file.

            return _infoPathAttachmentDecoder.DecodedFile;

        }

    }
}